
using AutoMapper;
using DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using Model;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using SqlSugar;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
using Util;

namespace API.Controllers
{
    public class WxController : BaseController
    {
        //微信服务接口路径
        private readonly string HOST = "http://msg.yingdl.com/";
        ////小影入园（小程序）
        private readonly string APPID_xcx = "wxdf8680bd07b9440a";//小程序ID
        private readonly string SECRET_xcx = "064586399eb4a7cd814bbd3592bb16bb";//小程序秘钥
        //影擎助手（公众号）
        readonly string APPID_gzh = "wx9e6076511a6c2b26";//公众号ID
        //readonly string SECRET_gzh = "700f32058109ad594b7c076a2da3c39d";//公众号秘钥
        readonly string TemplateID_gzh = "BwUyRPhYQWDhai2JrFdLpsKmQmm_HV3LaDI94xBsHLg";//模板ID
        Repository<tSign> _Sign;
        readonly IMapper _mapper;
        ISqlSugarClient _db;
        Repository<tAutoMealReporting> _auto;
        public WxController(Repository<tSign> Sign, IMapper mapper,ISqlSugarClient db, Repository<tAutoMealReporting> auto)
        {
            _Sign = Sign;
            _mapper = mapper;
            _db = db;
            _auto = auto;
        }
        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultMsg<string>> Save([FromBody] SaveSignInput dto)
        {
            ResultMsg<string> result = new ResultMsg<string>();
            try
            {
                var model = _mapper.Map<tSign>(dto);
                InitEntity(model);
                await _Sign.InsertOrUpdateAsync(model);
                return result.Success();
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--Save:" + ex.ToString());
                return result.Error(ex.ToString());
            }
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultMsg<List<SignOutput>>> GetList([FromBody] SignListInput dto)
        {
            ResultMsg<List<SignOutput>> result = new ResultMsg<List<SignOutput>>();
            try
            {
                Expressionable<tSign> expressionable = Expressionable.Create<tSign>();//实例化Expressionable
                expressionable.AndIF(dto.search != "#search", (sign) => sign.FCompany.Contains(dto.search) || sign.FName.Contains(dto.search));//添加查询条件
                expressionable.AndIF(dto.Personal != 0, (sign) => sign.FPersonal == (dto.Personal == 1 ? true : false));//是否个人
                expressionable.AndIF(dto.SourceID.Length > 0, (sign) => sign.FSourceID == dto.SourceID);
                expressionable.AndIF(dto.isFake, (sign) => sign.FFakeVisitNum > 0);
                expressionable.AndIF(true, sign => sign.CreateTime >= dto.start && sign.CreateTime <= dto.end);

                Expression<Func<tSign, bool>> expression = expressionable.ToExpression();//将Expressionable转为Expression

                int total = await _Sign.CountAsync(expression);

                dynamic d = await Task.Run(() => _db.Queryable<tSign, tSource, tSource>((sign, source, fakesource) => new object[] {
                    JoinType.Left,sign.FSourceID == source.Id,
                    JoinType.Left,sign.FFakeSourceID==fakesource.Id
                })
                .OrderBy(sign => sign.CreateTime, OrderByType.Desc)
                .Where(expression)
                .Select((sign, source, fakesource) => new SignOutput
                {
                    Id=sign.Id,
                    SourceID=sign.FSourceID,
                    FakeSourceID = sign.FFakeSourceID,
                    Personal = sign.FPersonal==true?"个人":"集体",
                    Name = sign.FName,
                    Phone = sign.FPhone,
                    Company = sign.FCompany,
                    VisitNum = sign.FVisitNum,
                    FakeVisitNum = sign.FFakeVisitNum,
                    Source = source.FName,
                    FakeSource = fakesource.FName
                })
                .Skip((dto.PageNum - 1) * dto.PageSize)
                .Take(dto.PageSize).ToList());
                return result.Success(d, total);
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--GetList:" + ex.ToString());
                return result.Error(ex.ToString());
            }
        }
        /// <summary>
        /// 获取唯一
        /// </summary>
        /// <param name="id">主键ID</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultMsg<SignOutput>> GetTheOne(string id)
        {
            ResultMsg<SignOutput> result = new ResultMsg<SignOutput>();
            try
            {
                var model = await _Sign.GetByIdAsync(id);
                var dao = _mapper.Map<SignOutput>(model);
                return result.Success(dao);
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--GetTheOne:" + ex.ToString());
                return result.Error(ex.ToString());
            }
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id">主键ID</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultMsg<string>> Del(string id)
        {
            ResultMsg<string> result = new ResultMsg<string>();
            try
            {
                await _Sign.DeleteByIdAsync(id);
                return result.Success();
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--Del:" + ex.ToString());
                return result.Error(ex.ToString());
            }
        }
        /// <summary>
        /// 获取签到汇总记录
        /// </summary>
        /// <param name="isFake">是否只看j数据</param>
        /// <param name="FSourceID">客户来源，全部0</param>
        /// <param name="FPersonal">个人1，集体2，全部0</param>
        /// <param name="start">开始时间</param>
        /// <param name="end">结束时间</param>
        /// <param name="order">分组时间格式</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultMsg<List<SignOutput>>> GetSignGroupDate(GetSignGroupInput input)
        {
            ResultMsg<List<SignOutput>> result = new ResultMsg<List<SignOutput>>();
            try
            {
                if (input.orderType!=null)
                {
                    return result.Error("分组字符串不能为空");
                }

                var exp = Expressionable.Create<tSign>();
                exp.And(sign => sign.CreateTime >= input.start && sign.CreateTime <= input.end);
                dynamic? d = default;
                if (input.orderType == 3)
                {
                    d = await Task.Run(() => _db.Queryable<tSign>().Where(exp.ToExpression())
                    .Select(sign => new
                    {
                        FCreateDate = sign.CreateTime.Year.ToString(),
                        FFakeVisitNum = sign.FFakeVisitNum == 0 ? sign.FVisitNum : sign.FFakeVisitNum,
                        sign.FVisitNum
                    }).MergeTable().GroupBy(g => new
                    {
                        g.FCreateDate
                    })
                    .Select(t => new SignOutput
                    {
                        CreateTime= t.FCreateDate,
                        FakeVisitNum = SqlFunc.AggregateSum(t.FFakeVisitNum),
                        VisitNum = SqlFunc.AggregateSum(t.FVisitNum)
                    }).OrderBy(t => t.CreateTime).ToList());
                }
                else if (input.orderType == 1 || input.orderType == 2)
                {
                    string order = input.orderType == 1 ? "yyyy-MM" : "yyyy-MM-dd";
                    d = await Task.Run(() => _db.Queryable<tSign>()
                        .Where(exp.ToExpression())
                        .Select(sign => new
                        {
                            FCreateDate = sign.CreateTime.ToString(order),
                            FFakeVisitNum = sign.FFakeVisitNum == 0 ? sign.FVisitNum : sign.FFakeVisitNum,
                            sign.FVisitNum
                        }).MergeTable().GroupBy(g => new
                        {
                            g.FCreateDate
                        })
                        .Select(t => new SignOutput
                        {
                            CreateTime = t.FCreateDate,
                            FakeVisitNum = SqlFunc.AggregateSum(t.FFakeVisitNum),
                            VisitNum = SqlFunc.AggregateSum(t.FVisitNum)
                        }).OrderBy(t => t.CreateTime).ToList());
                }
                    
                return result.Success(d);
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--GetSignGroupDate:" + ex.ToString());
                return result.Exception();
            }
        }
        /// <summary>
        /// 按客户性质分组
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultMsg<List<SignOutput>>> GetSignGroupByType(GetSignGroupInput input)
        {
            ResultMsg<List<SignOutput>> result = new ResultMsg<List<SignOutput>>();
            try
            {
                var exp = Expressionable.Create<tSign>();
                exp.And(sign => sign.CreateTime >= input.start && sign.CreateTime <= input.end);
                dynamic? d = await Task.Run(() => _db.Queryable<tSign>()
                        .Where(exp.ToExpression())
                        .Select((sign) => new
                        {
                            FPersonal = sign.FPersonal,
                            FFakeVisitNum = sign.FFakeVisitNum == 0 ? sign.FVisitNum : sign.FFakeVisitNum,
                            sign.FVisitNum
                        }).MergeTable().GroupBy(g => new
                        {
                            g.FPersonal
                        })
                        .Select(t => new SignOutput
                        {
                            Personal = t.FPersonal == true ? "个人" : "集体",
                            FakeVisitNum = SqlFunc.AggregateSum(t.FFakeVisitNum),
                            VisitNum = SqlFunc.AggregateSum(t.FVisitNum)
                        }).OrderBy(t => t.Personal).ToList());
                return result.Success(d);
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--GetSignGroupByType:" + ex.ToString());
                return result.Exception();
            }
        }
        /// <summary>
        /// 按客户来源分组
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="isfake"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultMsg<List<SignOutput>>> GetSignGroupBySoucre(GetSignGroupInput input)
        {
            ResultMsg<List<SignOutput>> result = new ResultMsg<List<SignOutput>>();
            try
            {
                var exp = Expressionable.Create<tSign>();
                exp.And(sign => sign.CreateTime >= input.start && sign.CreateTime <= input.end);

                if ((bool)input.isfake)
                {
                    dynamic? dd = await Task.Run(() => _db.Queryable<tSource>().LeftJoin<tSign>((source, sign) => source.Id == sign.FFakeSourceID && sign.CreateTime >= input.start && sign.CreateTime <= input.end)
                    .Where(source => source.FDeleted == false)
                    .Select((source, sign) => new
                    {
                        source.FDeleted,
                        FCreateDate = sign.CreateTime,
                        source.FName,
                        FFakeVisitNum = sign.FFakeVisitNum == 0 ? sign.FVisitNum : sign.FFakeVisitNum,
                        FVisitNum = sign.FVisitNum
                    })
                    .MergeTable().GroupBy(g => new
                    {
                        g.FName
                    })
                    .Select(t => new SignOutput
                    {
                        Name= t.FName,
                        FakeVisitNum = SqlFunc.AggregateSum(t.FFakeVisitNum),
                        VisitNum = SqlFunc.AggregateSum(t.FVisitNum)
                    }).OrderBy(t => t.Name).ToList());
                    return result.Success(dd);

                }

                dynamic? d = await Task.Run(() => _db.Queryable<tSource>().LeftJoin<tSign>((source, sign) => source.Id == sign.FSourceID && sign.CreateTime >= input.start && sign.CreateTime <= input.end)
                .Where(source => source.FDeleted == false)
                .Select((source, sign) => new
                {
                    source.FDeleted,
                    FCreateDate = sign.CreateTime,
                    source.FName,
                    FFakeVisitNum = sign.FFakeVisitNum == 0 ? sign.FVisitNum : sign.FFakeVisitNum,
                    FVisitNum = sign.FVisitNum
                })
                .MergeTable().GroupBy(g => new
                {
                    g.FName
                })
                .Select(t => new SignOutput
                {
                    Name= t.FName,
                    FakeVisitNum = SqlFunc.AggregateSum(t.FFakeVisitNum),
                    VisitNum = SqlFunc.AggregateSum(t.FVisitNum)
                }).OrderBy(t => t.Name).ToList());
                return result.Success(d);
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--GetSignGroupBySoucre:" + ex.ToString());
                return result.Exception();
            }
        }
        /// <summary>
        /// 获取用户电话
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public ResultMsg<string> GetUserPhoneNumber(string code)
        {
            ResultMsg<string> result = new ResultMsg<string>();
            try
            {
                string url = string.Format(HOST + @"Wechat/GetUserPhoneNumber?appid={0}&secret={1}&code={2}", APPID_xcx, SECRET_xcx, code);
                string res = HttpHelper.HttpGet(url);
                return result.Success(res);
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--GetUserPhoneNumber:" + ex.ToString());
                return result.Exception();
            }
        }

        /// <summary>
        /// 登录凭证
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public ResultMsg<string> Code2Session(string code)
        {
            ResultMsg<string> result = new ResultMsg<string>();
            try
            {
                string url = string.Format(HOST + @"Wechat/Code2Session?appid={0}&secret={1}&code={2}", APPID_xcx, SECRET_xcx, code);
                string res = HttpHelper.HttpGet(url);
                return result.Success(res);
            }
            catch (Exception ex)
            {
                Util.NLOG.LogHelper.Error("SignController--Code2Session:" + ex.ToString());
                return result.Error("下载异常");
            }
        }
    }
}
